package cn.iocoder.yudao.module.reading.controller.admin.file;

import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
import cn.iocoder.yudao.framework.common.exception.ServiceException;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.security.core.LoginUser;
import cn.iocoder.yudao.framework.security.core.annotations.PreAuthenticated;
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import cn.iocoder.yudao.module.infra.controller.admin.file.vo.file.FilePresignedUrlRespVO;
import cn.iocoder.yudao.module.reading.service.file.ReadingFileService;
import cn.iocoder.yudao.module.reading.framework.util.StaticResourceUrlUtils;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.validation.constraints.NotNull;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.util.Map;

import static cn.iocoder.yudao.framework.common.pojo.CommonResult.error;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;

/**
 * 管理后台 - 绘本文件管理
 *
 * @author 李晨
 */
@Tag(name = "管理后台 - 绘本文件管理")
@RestController
@RequestMapping("/reading/book-file")
@Validated
@Slf4j
public class AdminBookFileController {

    @Resource
    private ReadingFileService readingFileService;
    @Resource
    private StaticResourceUrlUtils staticResourceUrlUtils;

    /**
     * 测试当前用户信息
     */
    @GetMapping("/test-user")
    @Operation(summary = "测试当前用户信息")
    @PreAuthenticated
    public CommonResult<Object> testCurrentUser() {
        LoginUser loginUser = SecurityFrameworkUtils.getLoginUser();
        if (loginUser == null) {
            return success("用户未登录");
        }

        return success(Map.of(
            "userId", loginUser.getId(),
            "userType", loginUser.getUserType(),
            "userTypeEnum", UserTypeEnum.valueOf(loginUser.getUserType()),
            "adminValue", UserTypeEnum.ADMIN.getValue(),
            "isAdmin", UserTypeEnum.ADMIN.getValue().equals(loginUser.getUserType())
        ));
    }

    /**
     * 检查当前用户是否为管理员
     * 绘本文件上传只允许管理员操作
     */
    private void checkAdminPermission() {
        LoginUser loginUser = SecurityFrameworkUtils.getLoginUser();
        if (loginUser == null) {
            throw new ServiceException(401, "用户未登录");
        }
        log.info("当前登录用户信息: userId={}, userType={}", loginUser.getId(), loginUser.getUserType());
        if (!UserTypeEnum.ADMIN.getValue().equals(loginUser.getUserType())) {
            throw new ServiceException(403, "权限不足，只有管理员可以上传绘本文件。当前用户类型: " + loginUser.getUserType() + ", 需要类型: " + UserTypeEnum.ADMIN.getValue());
        }
    }

    // =============================================
    // 绘本集文件上传
    // =============================================

    @PostMapping("/book-set/{bookSetId}/cover")
    @Operation(summary = "上传绘本集封面")
    @PreAuthenticated
    public CommonResult<String> uploadBookSetCover(
            @Parameter(description = "绘本集ID") @PathVariable("bookSetId") Long bookSetId,
            @Parameter(description = "封面文件") @RequestParam("cover") MultipartFile coverFile) {

        // 检查管理员权限
        checkAdminPermission();

        log.info("上传绘本集封面，绘本集ID: {}, 文件名: {}", bookSetId, coverFile.getOriginalFilename());

        try {
            // 上传文件，服务层返回相对路径
            String relativePath = readingFileService.uploadBookSetCover(bookSetId, coverFile);
            // 转换为完整URL返回给前端
            String fullUrl = staticResourceUrlUtils.toFullUrl(relativePath);
            log.info("绘本集封面上传成功，相对路径: {}, 完整URL: {}", relativePath, fullUrl);

            return success(fullUrl);
        } catch (Exception e) {
            log.error("上传绘本集封面失败", e);
            return error(500, "上传封面失败: " + e.getMessage());
        }
    }

    @GetMapping("/book-set/{bookSetId}/cover/presigned-url")
    @Operation(summary = "获取绘本集封面上传预签名URL")
    @PreAuthenticated
    public CommonResult<FilePresignedUrlRespVO> getBookSetCoverPresignedUrl(
            @Parameter(description = "绘本集ID") @PathVariable("bookSetId") Long bookSetId,
            @Parameter(description = "文件名") @RequestParam("fileName") String fileName) {

        try {
            // 使用bookSetId作为bookId参数，因为绘本集封面不需要具体的绘本ID
            FilePresignedUrlRespVO presignedUrl = readingFileService.getBookCoverPresignedUrl(bookSetId, bookSetId, fileName);
            return success(presignedUrl);
        } catch (Exception e) {
            log.error("获取绘本集封面预签名URL失败", e);
            return error(500, "获取预签名URL失败: " + e.getMessage());
        }
    }

    // =============================================
    // 绘本文件上传
    // =============================================

    @PostMapping("/book-set/{bookSetId}/book/{bookId}/cover")
    @Operation(summary = "上传绘本封面")
    @PreAuthenticated
    public CommonResult<String> uploadBookCover(
            @Parameter(description = "绘本集ID") @PathVariable("bookSetId") Long bookSetId,
            @Parameter(description = "绘本ID") @PathVariable("bookId") Long bookId,
            @Parameter(description = "封面文件") @RequestParam("cover") MultipartFile coverFile) {

        log.info("上传绘本封面，绘本集ID: {}, 绘本ID: {}, 文件名: {}", bookSetId, bookId, coverFile.getOriginalFilename());

        try {
            // 上传文件，服务层返回相对路径
            String relativePath = readingFileService.uploadBookCover(bookSetId, bookId, coverFile);
            // 转换为完整URL返回给前端
            String fullUrl = staticResourceUrlUtils.toFullUrl(relativePath);
            log.info("绘本封面上传成功，相对路径: {}, 完整URL: {}", relativePath, fullUrl);

            return success(fullUrl);
        } catch (Exception e) {
            log.error("上传绘本封面失败", e);
            return error(500, "上传封面失败: " + e.getMessage());
        }
    }

    @PostMapping("/book-set/{bookSetId}/book/{bookId}/page/{pageNumber}")
    @Operation(summary = "上传绘本页面图片")
    @PreAuthenticated
    public CommonResult<String> uploadBookPage(
            @Parameter(description = "绘本集ID") @PathVariable("bookSetId") Long bookSetId,
            @Parameter(description = "绘本ID") @PathVariable("bookId") Long bookId,
            @Parameter(description = "页码") @PathVariable("pageNumber") Integer pageNumber,
            @Parameter(description = "页面图片文件") @RequestParam("page") MultipartFile pageFile) {

        log.info("上传绘本页面，绘本集ID: {}, 绘本ID: {}, 页码: {}, 文件名: {}",
                bookSetId, bookId, pageNumber, pageFile.getOriginalFilename());

        try {
            // 上传文件，服务层返回相对路径
            String relativePath = readingFileService.uploadBookPage(bookSetId, bookId, pageNumber, pageFile);
            // 转换为完整URL返回给前端
            String fullUrl = staticResourceUrlUtils.toFullUrl(relativePath);
            log.info("绘本页面上传成功，相对路径: {}, 完整URL: {}", relativePath, fullUrl);

            return success(fullUrl);
        } catch (Exception e) {
            log.error("上传绘本页面失败", e);
            return error(500, "上传页面失败: " + e.getMessage());
        }
    }

    @PostMapping("/book-set/{bookSetId}/book/{bookId}/audio")
    @Operation(summary = "上传绘本音频文件")
    @PreAuthenticated
    public CommonResult<String> uploadBookAudio(
            @Parameter(description = "绘本集ID") @PathVariable("bookSetId") Long bookSetId,
            @Parameter(description = "绘本ID") @PathVariable("bookId") Long bookId,
            @Parameter(description = "页码（可选）") @RequestParam(value = "pageNumber", required = false) Integer pageNumber,
            @Parameter(description = "音频文件") @RequestParam("audio") MultipartFile audioFile) {

        log.info("上传绘本音频，绘本集ID: {}, 绘本ID: {}, 页码: {}, 文件名: {}",
                bookSetId, bookId, pageNumber, audioFile.getOriginalFilename());

        try {
            // 上传文件，服务层返回相对路径
            String relativePath = readingFileService.uploadBookAudio(bookSetId, bookId, pageNumber, audioFile);
            // 转换为完整URL返回给前端
            String fullUrl = staticResourceUrlUtils.toFullUrl(relativePath);
            log.info("绘本音频上传成功，相对路径: {}, 完整URL: {}", relativePath, fullUrl);

            return success(fullUrl);
        } catch (Exception e) {
            log.error("上传绘本音频失败", e);
            return error(500, "上传音频失败: " + e.getMessage());
        }
    }

    @GetMapping("/book-set/{bookSetId}/book/{bookId}/cover/presigned-url")
    @Operation(summary = "获取绘本封面上传预签名URL")
    @PreAuthenticated
    public CommonResult<FilePresignedUrlRespVO> getBookCoverPresignedUrl(
            @Parameter(description = "绘本集ID") @PathVariable("bookSetId") Long bookSetId,
            @Parameter(description = "绘本ID") @PathVariable("bookId") Long bookId,
            @Parameter(description = "文件名") @RequestParam("fileName") String fileName) {
        
        try {
            FilePresignedUrlRespVO presignedUrl = readingFileService.getBookCoverPresignedUrl(bookSetId, bookId, fileName);
            return success(presignedUrl);
        } catch (Exception e) {
            log.error("获取绘本封面预签名URL失败", e);
            return error(500, "获取预签名URL失败: " + e.getMessage());
        }
    }

    @GetMapping("/book-set/{bookSetId}/book/{bookId}/page/{pageNumber}/presigned-url")
    @Operation(summary = "获取绘本页面上传预签名URL")
    @PreAuthenticated
    public CommonResult<FilePresignedUrlRespVO> getBookPagePresignedUrl(
            @Parameter(description = "绘本集ID") @PathVariable("bookSetId") Long bookSetId,
            @Parameter(description = "绘本ID") @PathVariable("bookId") Long bookId,
            @Parameter(description = "页码") @PathVariable("pageNumber") Integer pageNumber,
            @Parameter(description = "文件名") @RequestParam("fileName") String fileName) {
        
        try {
            FilePresignedUrlRespVO presignedUrl = readingFileService.getBookPagePresignedUrl(bookSetId, bookId, pageNumber, fileName);
            return success(presignedUrl);
        } catch (Exception e) {
            log.error("获取绘本页面预签名URL失败", e);
            return error(500, "获取预签名URL失败: " + e.getMessage());
        }
    }

    @GetMapping("/book-set/{bookSetId}/book/{bookId}/audio/presigned-url")
    @Operation(summary = "获取绘本音频上传预签名URL")
    @PreAuthenticated
    public CommonResult<FilePresignedUrlRespVO> getBookAudioPresignedUrl(
            @Parameter(description = "绘本集ID") @PathVariable("bookSetId") Long bookSetId,
            @Parameter(description = "绘本ID") @PathVariable("bookId") Long bookId,
            @Parameter(description = "页码（可选）") @RequestParam(value = "pageNumber", required = false) Integer pageNumber,
            @Parameter(description = "文件名") @RequestParam("fileName") String fileName) {

        try {
            // 注意：当前ReadingFileService接口中没有getBookAudioPresignedUrl方法
            // 这里返回一个提示信息，表示功能暂未实现
            return error(501, "绘本音频预签名URL功能暂未实现，请使用直接上传方式");
        } catch (Exception e) {
            log.error("获取绘本音频预签名URL失败", e);
            return error(500, "获取预签名URL失败: " + e.getMessage());
        }
    }

    // =============================================
    // 文件删除接口
    // =============================================

    @DeleteMapping("/delete")
    @Operation(summary = "删除文件")
    @PreAuthenticated
    public CommonResult<Boolean> deleteFile(@RequestParam("path") String relativePath) {
        // 检查管理员权限
        checkAdminPermission();

        log.info("删除文件，路径: {}", relativePath);

        try {
            boolean success = readingFileService.deleteFile(relativePath);
            if (success) {
                return success(true);
            } else {
                return error(500, "文件删除失败");
            }
        } catch (Exception e) {
            log.error("删除文件失败", e);
            return error(500, "删除文件失败: " + e.getMessage());
        }
    }
}
